/*    file: RtmpMediaSink.h
 *    desc:
 *   
 * created: 2016-06-12
 *  author: chuanjiang.zh@qq.com
 * company: 
 */ 


#if !defined RTMPMEDIASINK_H_
#define RTMPMEDIASINK_H_

#include "FileMediaSink.h"
#include "Ffmpeg.h"
#include "TCriticalSection.h"
#include "TThread.h"
#include "MediaPacketQueue.h"


namespace av
{

class RtmpMediaSink: public FileMediaSink, public comn::Thread
{
public:
	enum EventType
	{
		kOpening = 0x10,
		kOpened,
		kClosed,
		kOpenFault
	};

	class EventSink
	{
	public:
		virtual ~EventSink() {}
		virtual void onEvent(int type, const std::string& value) =0;
	};

public:
    RtmpMediaSink();
    virtual ~RtmpMediaSink();

    virtual bool open(const std::string& filepath);
    virtual void close();
    virtual bool isOpen();

    virtual std::string getFile();

    virtual int setFile(const std::string& filepath);

    virtual void onMediaFormat(const MediaFormat& fmt);

    virtual void onMediaPacket(MediaPacketPtr& pkt);

    virtual void onMediaEvent(int event);

    void setEventSink(EventSink* sink);

protected:
    virtual int run();
    virtual void doStop();

protected:
    int openFile();
    void closeFile();
    bool isFileOpen();
	
	bool tryOpenFile();

	void freeFormatContext(AVFormatContext* ctx);

    void addAdtsHeader(AVPacket* src, AVPacket* dst);

    bool handleMediaPacket(MediaPacketPtr& pkt);
    void handleCloseFile();

    void fireEvent(int event, const std::string& value = std::string());

	bool waitForWork(int ms);
	bool isWorking();

	void print(AVPacket& pkt);

protected:
    AVFormatContext*	m_fmtCtx;

    int	m_videoIndex;
    int	m_audioIndex;
    std::string	m_filename;
    MediaFormat	m_format;

    bool m_changeFile;

    comn::CriticalSection	m_cs;
    int64_t m_videoStartTime;
    int64_t m_audioStartTime;

    MediaPacketQueue    m_pktQueue;
    EventSink*	m_eventSink;

	comn::Event	m_event;
	bool	m_working;

	time_t	m_dropTime;
	int		m_idlePktCount;

};


} /* namespace av */


#endif //RTMPMEDIASINK_H_

